<!DOCTYPE html>
<html lang="zh">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>树形结构渲染</title>
    <style>
        * {
            margin: 0;
            padding: 0;
            box-sizing: border-box;
        }
        body {
            font-family: "PingFang SC", "Microsoft YaHei", sans-serif;
            padding: 20px;
            color: rgba(0, 0, 0, 0.85);
        }
        .tree {
            height: 200px;
            overflow: auto;
            border: 1px solid #f0f0f0;
            list-style-type: none;
            position: absolute;
            z-index: 100;
            background-color: #fff;
        }
        .container {
            max-width: 800px;
            margin: 0 auto;
        }
        h2 {
            margin-bottom: 20px;
        }

        /* 树形样式 */
        .tree-container {
            margin: 20px 0;
            border: 1px solid #f0f0f0;
            border-radius: 2px;
            padding: 15px;
        }
        .tree-node {
            padding: 4px 0;
        }
        .tree-children {
            list-style-type: none;
            padding-left: 20px;
            overflow: hidden;
            transition: all 0.3s;
        }
        .tree-node-content {
            display: flex;
            align-items: center;
            cursor: pointer;
            border-radius: 2px;
            padding: 3px 5px;
        }
        .tree-node-content:hover {
            background-color: #f5f5f5;
        }
        .tree-node-content.selected {
            background-color: #e6f7ff;
        }
        .tree-node-icon {
            width: 16px;
            height: 16px;
            display: inline-flex;
            align-items: center;
            justify-content: center;
            margin-right: 5px;
            font-size: 12px;
            transition: transform 0.3s;
        }
        .tree-node-title {
            flex: 1;
        }
        .expanded .tree-node-icon {
            transform: rotate(90deg);
        }
        .collapsed .tree-node-icon {
            transform: rotate(0deg);
        }
        .collapsed .tree-children {
            display: none;
        }
        .leaf .tree-node-icon {
            visibility: hidden;
        }

        /* 控制区域样式 */
        .controls {
            margin-bottom: 15px;
            padding: 10px;
            background-color: #f9f9f9;
            border-radius: 2px;
        }
        .btn {
            padding: 4px 15px;
            background: #fff;
            border: 1px solid #d9d9d9;
            border-radius: 2px;
            cursor: pointer;
            transition: all 0.3s;
            margin-right: 8px;
        }
        .btn:hover {
            color: #40a9ff;
            border-color: #40a9ff;
        }
        .btn-primary {
            color: #fff;
            background: #1890ff;
            border-color: #1890ff;
        }
        .btn-primary:hover {
            color: #fff;
            background: #40a9ff;
            border-color: #40a9ff;
        }
        .select {
            border: 1px solid #f0f0f0;
            position: relative;
        }
        .checkbox {
            height: 20px;
            width: 20px;
            border: 1px solid;
            border-radius: 3px;
            display: inline-block;
            position: relative;
        }

        .checkbox-pendding::after {
            content: ' ';
            display: inline-block;
            padding:30%;
            background-color: blue;
            position: absolute;
            left: 50%;
            top: 50%;
            transform: translate(-50%, -50%);

        }
        /* 模拟checkbox选中状态 */
        .checkbox-completed::after {
            content: '✔';
            height: 100%;
            width: 100%;
            display: inline-block;
            background-color: blue;
            color: #fff;
            position: absolute;
            text-align: center;
        }
        
        .hidden {
            display: none;
        }
       
        
    </style>
</head>
<body>
    <div class="container">
        <h2>树形结构渲染示例</h2>
        <div id="zselect"></div>
        11223
    </div>

    <script>
        // 树形数据
        const treeData = [
            {
                id: 1,
                title: '分类 1',
                children: [
                    {
                        id: 11,
                        title: '分类 1-1'
                    },
                    {
                        id: 12,
                        title: '分类 1-2',
                        children: [
                            {
                                id: 121,
                                title: '分类 1-2-1'
                            },
                            {
                                id: 122,
                                title: '分类 1-2-2'
                            },
                            {
                                id: 123,
                                title: '分类 1-2-3'
                            }
                        ]
                    },
                    {
                        id: 13,
                        title: '分类 1-3',
                        children: [
                            {
                                id: 131,
                                title: '分类 1-3-1'
                            },
                            {
                                id: 132,
                                title: '分类 1-3-2'
                            },
                            {
                                id: 133,
                                title: '分类 1-3-3',
                                children: [
                                    {
                                        id: 1331,
                                        title: '分类 1-3-3-1'
                                    },
                                    {
                                        id: 1332,
                                        title: '分类 1-3-3-2'
                                    },
                                    {
                                        id: 1333,
                                        title: '分类 1-3-3-3'
                                    }
                                ]
                            }
                        ]
                    }
                ]
            },
            {
                id: 2,
                title: '分类 2',
                children: [
                    {
                        id: 21,
                        title: '分类 2-1'
                    },
                    {
                        id: 22,
                        title: '分类 2-2'
                    }
                ]
            },
            {
                id: 3,
                title: '分类 3'
            },
            {
                id: 4,
                title: '分类 4',
                children: [
                    {
                        id: 41,
                        title: '分类 4-1'
                    }
                ]
            },
            {
                id: 5,
                title: '分类 5',
                children: [
                    {
                        id: 51,
                        title: '分类 5-1'
                    }
                ]
            },{
                id: 6,
                title: '分类 6',
                children: [
                    {
                        id: 61,
                        title: '分类 6-1'
                    }
                ]
            },{
                id: 7,
                title: '分类 7',
                children: [
                    {
                        id: 71,
                        title: '分类 7-1'
                    }
                ]
            },{
                id: 8,
                title: '分类 8',
                children: [
                    {
                        id: 81,
                        title: '分类 8-1'
                    }
                ]
            }
        ];

        // 递归渲染树形结构
        /**
         * data
         * parentElement
         * mult 是否是单选
         */
        // data, parentElement, mult
        function renderTree(obj) {
            obj.treeData.forEach(node => {
                // 创建节点元素
                const li = document.createElement('li');
                li.className = 'tree-node';
                if (!node.children || node.children.length === 0) {
                    li.classList.add('leaf');
                } else {
                    li.classList.add('root');
                    li.classList.add('collapsed');
                }

                // 创建节点内容
                const nodeContent = document.createElement('div');
                nodeContent.className = 'tree-node-content';
                nodeContent.dataset.id = node.id;
                
                // 创建展开/折叠图标
                const icon = document.createElement('span');
                icon.className = 'tree-node-icon';
                icon.innerHTML = '▶';

                icon.onclick = function() {
                    let node = this.closest('.tree-node')
                    if (node.classList.contains('leaf')) return;

                    if (node.classList.contains('expanded')) {
                        node.classList.remove('expanded');
                        node.classList.add('collapsed');
                    } else {
                        node.classList.remove('collapsed');
                        node.classList.add('expanded');
                    }
                }
                nodeContent.appendChild(icon);
                // checkbox
                const checkbox = document.createElement('div');
                checkbox.className = 'checkbox';
                checkbox.data = node
                if (!node.children || node.children.length === 0) {
                    checkbox.expand = 'check-leaf';
                } else {
                    checkbox.expand = 'check-root';
                }

                checkbox.onclick = function() {
                    if(this.className == 'checkbox') {
                        this.className = 'checkbox checkbox-completed'
                    }else {
                        this.className = 'checkbox'
                    }
                    // 选中所有子集
                    this.closest('li').querySelectorAll('.checkbox').forEach(el=> {
                        el.className = this.classList
                    })
                    obj.onSelected&& obj.onSelected(this)

                    // 父级
                    parentUpdateEle(this.closest('.root'))
                }

                nodeContent.appendChild(checkbox);

                // 创建节点标题
                const title = document.createElement('span');
                title.className = 'tree-node-title';
                title.textContent = node.title;
                nodeContent.appendChild(title);

                li.appendChild(nodeContent);

                // 如果有子节点，递归渲染
                if (node.children && node.children.length > 0) {
                    const ul = document.createElement('ul');
                    ul.className = 'tree-children';
                    li.appendChild(ul);
                    // 递归渲染子节点
                    renderTree({...obj, treeData: node.children, treeElement:ul});
                }
                obj.treeElement.appendChild(li);
            });
            return obj.treeElement
        }

        function parentUpdateEle(node) {
            if(!node) return
            let checkArr = []
            node.querySelectorAll('.checkbox').forEach((el, index)=> {
                if(index == 0) return
                checkArr.push(el.classList.value.includes('checkbox-completed'))
            })
            const obj = node.querySelector('.checkbox')
            if(checkArr.every(item=>item==true))  {
                obj.className  = 'checkbox checkbox-completed'
            } else if(checkArr.some(item=>item==true))  {
                obj.className  = 'checkbox checkbox-pendding'
            }else {
                obj.className  = 'checkbox'
            }
            if(node.parentElement.closest('.root')) {
                parentUpdateEle(node.parentElement.closest('.root'))
            }
        }

        function select2(obj) {
            const dv = document.createElement('div')
                  dv.className = 'select'
                  dv.onmouseleave = function() {
                    !this.querySelector('.tree').classList.value.includes('hidden')&&
                    this.querySelector('.tree').classList.add('hidden')
                  }
            const div = document.createElement('div')
            div.className = 'sel'
            div.onclick = function() {
                this.nextElementSibling.classList.toggle('hidden')
                
            }
            const dvL = document.createElement('div')
            
            const dvR = document.createElement('div')
            dvR.innerText = '^'

            div.appendChild(dvL)
            div.appendChild(dvR)
            dv.appendChild(div)

            const ul = document.createElement('ul')
            ul.id = 'tree'
            ul.className = 'tree hidden'
           dv.appendChild(renderTree({
                treeElement: ul,
                ...obj
            }))
            obj.zselect.appendChild(dv)
        }

        
        // 初始化
        function init() {
            const treeElement = document.getElementById('tree');
            const zselect = document.getElementById('zselect')
            select2({
                treeData:treeData, 
                zselect:zselect,
                selectVal: [11, 121],
                mult:true,
                onSelected: function(node){
                    const arr = []
                    node.closest('.tree').querySelectorAll('.leaf').forEach(res=>{
                        res.querySelector('.checkbox-completed')&&  arr.push(res.querySelector('.checkbox-completed')?.data)
                    })
                    console.log(arr)
                }
            })
        }

        // 页面加载完成后初始化
        document.addEventListener('DOMContentLoaded', init);
    </script>
</body>
</html>